from plistlib import InvalidFileException
from zipfile import BadZipfile
from django import forms
from django.db.models import Q
from django.shortcuts import render
from django.http import HttpResponse, request, HttpResponseBadRequest
from app01 import models
import logging
from openpyxl import load_workbook
from django.shortcuts import redirect
import os
import pandas as pd
from django.http import HttpResponse, HttpResponseBadRequest
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.shortcuts import redirect




from app01.pagination import Pagination

logger = logging.getLogger(__name__)

class BootStrapModelForm(forms.ModelForm):
    """
    该类用于生成带有Bootstrap样式的ModelForm。
    它会自动为每个字段的Widget添加Bootstrap样式类和其他属性。
    """

    def __init__(self, *args, **kwargs):
        """
        初始化方法，用于设置ModelForm字段的Widget属性。

        参数:
        *args: 位置参数，传递给父类的初始化方法。
        **kwargs: 关键字参数，传递给父类的初始化方法。
        """
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段，给每个字段的插件设置
        for name, field in self.fields.items():
            # 字段中有属性，保留原来的属性，没有属性，才增加。
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {
                    "class": "form-control",
                    "placeholder": field.label
                }

# Create your views here.
class MyForm(BootStrapModelForm):
    # 定义表单类，继承自BootStrapModelForm，用于用户信息的展示和编辑
    class Meta:
        # 指定模型来源和表单中包含的字段
        model = models.User_info
        # 选择用户信息模型中的特定字段以包含在此表单中
        fields = ['username', 'department', 'group', 'phone_number', 'description']

def depart_add(request):
    try:
        # 验证请求方法是否为 GET 或 POST
        if request.method not in ["GET", "POST"]:
            return HttpResponseBadRequest("Invalid request method")

        if request.method == "GET":
            # 创建空表单实例
            form = MyForm()
            # 返回渲染后的页面
            return render(request, 'user_info/depart_add.html', {"form": form})

        elif request.method == "POST":
            # 使用 POST 数据创建表单实例
            form = MyForm(request.POST)

            # 验证表单数据
            if form.is_valid():
                # 保存数据到数据库
                form.save()
                # 返回成功响应
                return redirect("/user_info/depart/list")

            else:
                # 表单数据无效时返回错误响应
                logger.error(f"Invalid form data: {form.errors}")
                return HttpResponseBadRequest("表单数据无效")

    except Exception as e:
        # 记录详细的错误日志
        logger.error(f"An error occurred: {e}")
        return HttpResponseBadRequest("An error occurred while processing the request.")

def depart_list(request):
    """
    获取用户信息并渲染部门列表页面。

    本函数查询所有用户信息对象，并将其传递给部门列表模板进行渲染。
    主要用于展示各部门的信息，并允许对这些部门信息进行操作，如查看、编辑、删除等。

    参数:
    - request: HTTP请求对象，包含了请求的元数据和请求内容。

    返回:
    - render: 渲染后的HTML页面，包含部门列表信息。
    """
    try:
        # 查询用户信息对象
        values = request.GET.get('values', '')
        print(values)
        if values:
            # 使用 Q 对象进行跨字段模糊搜索
            queryset = models.User_info.objects.filter(
                Q(username__icontains=values) |
                Q(department__icontains=values) |
                Q(group__icontains=values) |
                Q(phone_number__icontains=values) |
                Q(description__icontains=values)
            )
            # 添加其他你想搜索的字段
        else:
            queryset = models.User_info.objects.all()
        page_object = Pagination(request, queryset)

        context = {
            "values": values,
            "queryset": page_object.page_queryset,  # 分完页的数据
            "page_string": page_object.html()  # 页码
        }
        # 渲染部门列表页面，并将查询到的用户信息对象传递给模板
        return render(request, 'user_info/depart_list.html', context)


    except Exception as e:
        logger.error(f"Error occurred while fetching user info: {e}")
        return HttpResponseBadRequest("获取用户信息时发生错误")

def depart_edit(request, nid):
    """
    编辑部门信息。

    本函数根据部门ID获取用户信息对象，并将其传递给编辑表单模板进行渲染。
    主要用于编辑部门信息，并提交编辑后的数据。

    参数:
    - request: HTTP请求对象，包含了请求的元数据和请求内容。
    - pk: 部门ID，用于获取对应的用户信息对象。
    返回:
    - render: 渲染后的HTML页面，包含编辑表单。
    """
    row_object = models.User_info.objects.filter(id=nid).first()
    if request.method == "GET":
        form = MyForm(instance=row_object)
        return render(request, 'user_info/depart_edit.html', {'form': form})
    form = MyForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/user_info/depart/list")
    return render(request, 'user_info/depart_edit.html', {'form': form})
def depart_delete(request, nid):
    try:
        # 尝试查找要删除的用户信息对象
        user_info = models.User_info.objects.filter(id=nid).first()
        if user_info:
            user_info.delete()  # 如果找到，进行删除操作
            return redirect("/user_info/depart/list")
        else:
            logger.warning(f"No user info found with id: {nid}")
            return HttpResponseBadRequest("用户信息不存在")
    except Exception as e:
        logger.error(f"An error occurred while deleting user info: {e}")
        return HttpResponseBadRequest("删除用户信息时发生错误")

def download_file(request):
    return render(request, 'user_info/download_file.html')
def upload_file(request):
    return render(request, 'user_info/upload_file.html')

def read_excel_file(file_object):
    try:
        wb = load_workbook(file_object)
        sheet = wb.worksheets[0]
        data = []
        for row in sheet.iter_rows(min_row=2):
            username = row[0].value
            department = row[1].value
            group = row[2].value
            phone_number = row[3].value
            description = row[4].value
            data.append((username, department, group, phone_number, description))
        return data
    except (BadZipfile, InvalidFileException) as e:
        raise ValueError(f"Error reading file: {e}")

def process_data(data):

    existing_titles = set(models.User_info.objects.values_list('username', 'department', 'group', 'phone_number', 'description'))

    new_records = []

    for username, department, group, phone_number, description in data:
        title = f"{username} {department} {group} {phone_number} {description}"
        if title not in existing_titles:
            new_records.append(models.User_info(
                username=username,
                department=department,
                group=group,
                phone_number=phone_number,
                description=description,
            ))

    return new_records

def save_records(new_records):
    models.User_info.objects.bulk_create(new_records)

def depart_multi(request):
    # 获取用户上传的文件对象
    file_object = request.FILES.get("exc")

    # 验证文件类型
    if not file_object or not file_object.name.endswith(('.xlsx', '.xls')):
        return HttpResponseBadRequest("Invalid file type. Only .xlsx and .xls files are allowed.")

    try:
        # 读取 Excel 文件数据
        data = read_excel_file(file_object)

        # 处理数据
        new_records = process_data(data)

        # 保存新记录
        save_records(new_records)

    except ValueError as e:
        return HttpResponseBadRequest(str(e))

    return redirect('/user_info/depart/list/')

def export_to_excel(request):
    # 获取所有 User_info 记录
    queryset = models.User_info.objects.all()

    # 将查询集转换为 DataFrame
    # data = list(queryset.values()).exclude('id')  # 这里使用 exclude('id') 方法
    data = list(queryset.values('username', 'department', 'group', 'phone_number', 'description'))
    df = pd.DataFrame(data)

    # 生成 Excel 文件
    try:
        # 创建临时文件
        temp_file = default_storage.save('temp_user_info.xlsx', ContentFile(b''))
        temp_file_path = default_storage.path(temp_file)

        # 将 DataFrame 写入 Excel 文件
        df.to_excel(temp_file_path, index=False)

        # 读取文件内容
        with open(temp_file_path, 'rb') as excel_file:
            response = HttpResponse(excel_file.read(), content_type='application/vnd.ms-excel')
            response['Content-Disposition'] = 'attachment; filename="业务归属部门管理列表.xlsx"'

        # 删除临时文件
        default_storage.delete(temp_file_path)

        return response

    except Exception as e:
        return HttpResponseBadRequest(f"Error exporting data to Excel: {e}")



